home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / PsdImagePlugin.py < prev    next >
Text File  |  2006-12-03  |  7KB  |  272 lines

  1. #
  2. # The Python Imaging Library
  3. # $Id: PsdImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
  4. #
  5. # Adobe PSD 2.5/3.0 file handling
  6. #
  7. # History:
  8. # 1995-09-01 fl   Created
  9. # 1997-01-03 fl   Read most PSD images
  10. # 1997-01-18 fl   Fixed P and CMYK support
  11. # 2001-10-21 fl   Added seek/tell support (for layers)
  12. #
  13. # Copyright (c) 1997-2001 by Secret Labs AB.
  14. # Copyright (c) 1995-2001 by Fredrik Lundh
  15. #
  16. # See the README file for information on usage and redistribution.
  17. #
  18.  
  19. __version__ = "0.4"
  20.  
  21. import string
  22. import Image, ImageFile, ImagePalette
  23.  
  24. MODES = {
  25.     # (photoshop mode, bits) -> (pil mode, required channels)
  26.     (0, 1): ("1", 1),
  27.     (0, 8): ("L", 1),
  28.     (1, 8): ("L", 1),
  29.     (2, 8): ("P", 1),
  30.     (3, 8): ("RGB", 3),
  31.     (4, 8): ("CMYK", 4),
  32.     (7, 8): ("L", 1), # FIXME: multilayer
  33.     (8, 8): ("L", 1), # duotone
  34.     (9, 8): ("LAB", 3)
  35. }
  36.  
  37. #
  38. # helpers
  39.  
  40. def i16(c):
  41.     return ord(c[1]) + (ord(c[0])<<8)
  42.  
  43. def i32(c):
  44.     return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
  45.  
  46. # --------------------------------------------------------------------.
  47. # read PSD images
  48.  
  49. def _accept(prefix):
  50.     return prefix[:4] == "8BPS"
  51.  
  52. ##
  53. # Image plugin for Photoshop images.
  54.  
  55. class PsdImageFile(ImageFile.ImageFile):
  56.  
  57.     format = "PSD"
  58.     format_description = "Adobe Photoshop"
  59.  
  60.     def _open(self):
  61.  
  62.         read = self.fp.read
  63.  
  64.         #
  65.         # header
  66.  
  67.         s = read(26)
  68.         if s[:4] != "8BPS" or i16(s[4:]) != 1:
  69.             raise SyntaxError, "not a PSD file"
  70.  
  71.         psd_bits = i16(s[22:])
  72.         psd_channels = i16(s[12:])
  73.         psd_mode = i16(s[24:])
  74.  
  75.         mode, channels = MODES[(psd_mode, psd_bits)]
  76.  
  77.         if channels > psd_channels:
  78.             raise IOError, "not enough channels"
  79.  
  80.         self.mode = mode
  81.         self.size = i32(s[18:]), i32(s[14:])
  82.  
  83.         #
  84.         # color mode data
  85.  
  86.         size = i32(read(4))
  87.         if size:
  88.             data = read(size)
  89.             if mode == "P" and size == 768:
  90.                 self.palette = ImagePalette.raw("RGB;L", data)
  91.  
  92.         #
  93.         # image resources
  94.  
  95.         self.resources = []
  96.  
  97.         size = i32(read(4))
  98.         if size:
  99.             # load resources
  100.             end = self.fp.tell() + size
  101.             while self.fp.tell() < end:
  102.                 signature = read(4)
  103.                 id = i16(read(2))
  104.                 name = read(ord(read(1)))
  105.                 if not (len(name) & 1):
  106.                     read(1) # padding
  107.                 data = read(i32(read(4)))
  108.                 if (len(data) & 1):
  109.                     read(1) # padding
  110.                 self.resources.append((id, name, data))
  111.  
  112.         #
  113.         # layer and mask information
  114.  
  115.         self.layers = []
  116.  
  117.         size = i32(read(4))
  118.         if size:
  119.             end = self.fp.tell() + size
  120.             size = i32(read(4))
  121.             if size:
  122.                 self.layers = _layerinfo(self.fp)
  123.             self.fp.seek(end)
  124.  
  125.         #
  126.         # image descriptor
  127.  
  128.         self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
  129.  
  130.         # keep the file open
  131.         self._fp = self.fp
  132.         self.frame = 0
  133.  
  134.     def seek(self, layer):
  135.         # seek to given layer (1..max)
  136.         if layer == self.frame:
  137.             return
  138.         try:
  139.             if layer <= 0:
  140.                 raise IndexError
  141.             name, mode, bbox, tile = self.layers[layer-1]
  142.             self.mode = mode
  143.             self.tile = tile
  144.             self.frame = layer
  145.             self.fp = self._fp
  146.             return name, bbox
  147.         except IndexError:
  148.             raise EOFError, "no such layer"
  149.  
  150.     def tell(self):
  151.         # return layer number (0=image, 1..max=layers)
  152.         return self.frame
  153.  
  154.     def load_prepare(self):
  155.         # create image memory if necessary
  156.         if not self.im or\
  157.            self.im.mode != self.mode or self.im.size != self.size:
  158.             self.im = Image.core.fill(self.mode, self.size, 0)
  159.         # create palette (optional)
  160.         if self.mode == "P":
  161.             Image.Image.load(self)
  162.  
  163. def _layerinfo(file):
  164.     # read layerinfo block
  165.     layers = []
  166.     read = file.read
  167.  
  168.     for i in range(abs(i16(read(2)))):
  169.  
  170.         # bounding box
  171.         y0 = i32(read(4)); x0 = i32(read(4))
  172.         y1 = i32(read(4)); x1 = i32(read(4))
  173.  
  174.         # image info
  175.         info = []
  176.         mode = []
  177.         for i in range(i16(read(2))):
  178.             type = i16(read(2))
  179.             if type == 65535:
  180.                 m = "A"
  181.             else:
  182.                 m = "RGB"[type]
  183.             mode.append(m)
  184.             size = i32(read(4))
  185.             info.append((m, size))
  186.  
  187.         # figure out the image mode
  188.         mode.sort()
  189.         if mode == ["R"]:
  190.             mode = "L"
  191.         elif mode == ["B", "G", "R"]:
  192.             mode = "RGB"
  193.         elif mode == ["A", "B", "G", "R"]:
  194.             mode = "RGBA"
  195.         else:
  196.             mode = None # unknown
  197.  
  198.         # skip over blend flags and extra information
  199.         filler = read(12)
  200.         name = None # FIXME
  201.         file.seek(i32(read(4)), 1)
  202.  
  203.         layers.append((name, mode, (x0, y0, x1, y1)))
  204.  
  205.     # get tiles
  206.     i = 0
  207.     for name, mode, bbox in layers:
  208.         tile = []
  209.         for m in mode:
  210.             t = _maketile(file, m, bbox, 1)
  211.             if t:
  212.                 tile.extend(t)
  213.         layers[i] = name, mode, bbox, tile
  214.         i = i + 1
  215.  
  216.     return layers
  217.  
  218. def _maketile(file, mode, bbox, channels):
  219.  
  220.     tile = None
  221.     read = file.read
  222.  
  223.     compression = i16(read(2))
  224.  
  225.     xsize = bbox[2] - bbox[0]
  226.     ysize = bbox[3] - bbox[1]
  227.  
  228.     offset = file.tell()
  229.  
  230.     if compression == 0:
  231.         #
  232.         # raw compression
  233.         tile = []
  234.         for channel in range(channels):
  235.             layer = mode[channel]
  236.             if mode == "CMYK":
  237.                 layer = layer + ";I"
  238.             tile.append(("raw", bbox, offset, layer))
  239.             offset = offset + xsize*ysize
  240.  
  241.     elif compression == 1:
  242.         #
  243.         # packbits compression
  244.         i = 0
  245.         tile = []
  246.         bytecount = read(channels * ysize * 2)
  247.         offset = file.tell()
  248.         for channel in range(channels):
  249.             layer = mode[channel]
  250.             if mode == "CMYK":
  251.                 layer = layer + ";I"
  252.             tile.append(
  253.                 ("packbits", bbox, offset, layer)
  254.                 )
  255.             for y in range(ysize):
  256.                 offset = offset + i16(bytecount[i:i+2])
  257.                 i = i + 2
  258.  
  259.     file.seek(offset)
  260.  
  261.     if offset & 1:
  262.         read(1) # padding
  263.  
  264.     return tile
  265.  
  266. # --------------------------------------------------------------------
  267. # registry
  268.  
  269. Image.register_open("PSD", PsdImageFile, _accept)
  270.  
  271. Image.register_extension("PSD", ".psd")
  272.